//============================================================================
// Copyright (C) 2008-2013 Brett R. Jones 
//
// Issued to public domain 2013
//
// brettjones1900@gmail.com
// http://www.p2panarchy.com
//============================================================================
#include "VxNetLib.h"
#include "VxSktBuf.h"
#include <memory.h>

#define VXSKT_ENABLE_BUF_LOCKS 1

//============================================================================
//=== constructor ===//
VxSktBuf::VxSktBuf( int iBufSize )
	: m_pau8SktBuf(0)			// socket buffer
	, m_iSktBufSize(iBufSize)	// total size of buffer
	, m_iSktBufIdx(0)			// current index into buffer
	, m_bFirstRxPacket(1)		// app can set if is first packet or not
	, m_bFirstTxPacket(1)		// app can set if is first packet or not
	//=== encryption vars ===//
	, m_u32RxDecryptedLen(0)	// amount of receive data decrypted
{
	vx_assert( iBufSize );
	m_pau8SktBuf = new U8[ iBufSize + 24 ];
}
//============================================================================
//=== destructor ===//
VxSktBuf::~VxSktBuf()
{
	if( m_pau8SktBuf )
	{
		delete m_pau8SktBuf;
	}
}

//============================================================================
//=== read from buf functions called by application ===//
//============================================================================
//============================================================================
//! get amount of date available
int VxSktBuf::GetSktBufDataLen( void )
{
	return m_iSktBufIdx;
}
//============================================================================
// app should get the buffer ( this also locks it from being modified by threads )
// then read the data then call Amount read
char * VxSktBuf::GetSktReadBuf( void )
{
#ifdef VXSKT_ENABLE_BUF_LOCKS
	m_oMutex.Lock(__FILE__, __LINE__);
#endif // VXSKT_ENABLE_BUF_LOCKS
	return (char *)m_pau8SktBuf;
}
//============================================================================
//! tell buffer how much was read.. also releases lock.. return -1 if larger amount than possible
RCODE VxSktBuf::SktBufAmountRead( int iAmountRead )
{
	if( iAmountRead > m_iSktBufIdx )
	{
		#ifdef VXSKT_ENABLE_BUF_LOCKS
			m_oMutex.Unlock(__FILE__, __LINE__);
		#endif // VXSKT_ENABLE_BUF_LOCKS
		vx_assert( false );
		return -1;
	}
	if( iAmountRead )
	{
		if( m_u32RxDecryptedLen )
		{
			vx_assert( (int)m_u32RxDecryptedLen >= iAmountRead );
			m_u32RxDecryptedLen -= iAmountRead;
		}
		if( iAmountRead < m_iSktBufIdx )
		{
			//got some left over
			int iAmountLeft = m_iSktBufIdx - iAmountRead;
			memcpy( m_pau8SktBuf, &m_pau8SktBuf[ iAmountRead ], iAmountLeft );
			m_iSktBufIdx = iAmountLeft;
		}
		else
		{
			m_iSktBufIdx = 0;
		}
	}
	#ifdef VXSKT_ENABLE_BUF_LOCKS
		m_oMutex.Unlock(__FILE__, __LINE__);
	#endif // VXSKT_ENABLE_BUF_LOCKS
	return 0;
}


//============================================================================
//=== write to buf functions called by socket threads ===//
//============================================================================
//============================================================================
//! get amount of space available
int VxSktBuf::GetSktBufFreeSpace( void )
{
	return m_iSktBufSize - m_iSktBufIdx;
}
//============================================================================
//! get the buffer to write into.. this also locks it
U8 * VxSktBuf::GetSktWriteBuf( void )
{
	#ifdef VXSKT_ENABLE_BUF_LOCKS
		m_oMutex.Lock(__FILE__, __LINE__);
	#endif // VXSKT_ENABLE_BUF_LOCKS
	return &m_pau8SktBuf[ m_iSktBufIdx ];
}

//============================================================================
//! tell buffer how much was written.. also releases lock.. return -1 if larger amount than possible
RCODE VxSktBuf::SktBufAmountWrote( int iAmountWrote )
{
	if( iAmountWrote > GetSktBufFreeSpace() )
	{
		#ifdef VXSKT_ENABLE_BUF_LOCKS
			m_oMutex.Unlock(__FILE__, __LINE__);
		#endif // VXSKT_ENABLE_BUF_LOCKS
		vx_assert( false );
		return -1;
	}
	m_iSktBufIdx += iAmountWrote;
	// null terminate just in case
	m_pau8SktBuf[ m_iSktBufIdx ] = 0;
	#ifdef VXSKT_ENABLE_BUF_LOCKS
		m_oMutex.Unlock( __FILE__, __LINE__);
	#endif // VXSKT_ENABLE_BUF_LOCKS
	return 0;
}

